//
//  CTVChannelPlayerController.m
//  Channltv
//
//  Created by Bruno Keymolen on 20/09/07.
//  Copyright 2007 channl.tv All rights reserved.
//

#import "CTVChannelPlayerController.h"
#import "CTVCache.h"
#import "CTVMediaDownloadController.h"
#import "CTVConfig.h"
#import "CTVNavigationManager.h"
#import "CTVChannel.h"

@implementation CTVChannelPlayerController

-(id)initWithScene:(BRRenderScene*)scene forChannel:(CTVChannel*)channel startWithClip:(CTVClip*)clip{
	self = [super initWithScene:scene];
	if(self == nil){
		return nil;
	}
	
	m_stopPlaying = NO;
		
//	m_clip = clip;
//	m_channel = channel;  //DEPRECATED
//	[m_clip retain]; //Why was this removed???
//	[m_channel retain];
	
	//Init the navigation manager, this will lead us through the clips and channels
	[[CTVNavigationManager GetInstance] setEntryPoint:clip];
	
	//[[CTVNavigationManager GetInstance] currentClip] -> pointer

//	m_videoPlayerController = [[BRVideoPlayerController alloc] initWithScene:[self scene]];
	m_rateController = [[CTVRateMediaController alloc] initWithScene:[self scene] andClip:clip];
	m_bgimage = [[BRImageControl alloc] initWithScene: [self scene]];

	m_channelSwtichInvoked = FALSE;

	m_showInfoController = nil;
	//[self addControl:m_bgimage];
	
	//[self _layout];
	
	return self;
}

-(void)dealloc{
//	if(m_clip != nil){
//		[m_clip release]; //Why was this removed???
//	}
//	[m_channel release];

	[m_rateController release];
	[m_bgimage release];
	
	if(m_playClipTimer){
		[m_playClipTimer invalidate];
	}
	if(m_channelSwitchTimer){
		[m_channelSwitchTimer invalidate];
	}	
	if(m_introID != nil){
		[m_introID release];
	}

	if(m_videoPlayerController != nil){
		[m_videoPlayerController release];
	}
	if(m_downloadController != nil){
		[m_downloadController release];
	}
	if(m_introController != nil){
		[m_introController release];
	}

	if(m_channelSwitchController != nil){
		[m_channelSwitchController release];
	}
	
	if(m_showInfoController != nil){
		[m_showInfoController release];
	}
	
	
	[super dealloc];
}

-(void)setClip:(CTVClip*)clip{
	[[CTVNavigationManager GetInstance] setEntryPoint:clip];
}

-(CTVClip*)clip{
	CTVClip* clip = [[CTVNavigationManager GetInstance] currentClip]; 
	return clip;
}



//If in cache -> play the clip ( [[CTVNavigationManager GetInstance] currentClip] )
//If not in cache -> start caching and show download screen
-(void)playClip{
	NSURL* mediaURL;
	NSString* urlString;
	NSError *error = [[NSError alloc] init];

	CTVClip* clip = [[CTVNavigationManager GetInstance] currentClip]; 
	
	if(clip == nil){
		NSLog( @"There is no current clip, probably you have seen the last added clip for this channel. Reposition the watchpointer.\n");
		return;
	}
	
	CTVChannel* channel = [clip pChannel];
	
	[clip retain]; //be sure to keep them in memory in this routine (sync can delete them in another thread)
	[channel retain];
	 
	urlString = [clip getUrl];

	NSString* cacheEntry = [CTVCache getMediaCacheEntryForURL:[clip getUrl]];		

	NSLog( @"Play Clip: [%@] cache: [%@]\n", urlString, cacheEntry);

	
	/*
	 * Channel switch, show channel name first
	 */
//	if(m_channelSwtichInvoked == TRUE){
//		m_channelSwtichInvoked = FALSE;
//		if(m_channelSwitchController != nil){
//			[m_channelSwitchController release];
//		}
//		m_channelSwitchController = [[CTVChannelSwitchInfoController alloc] initWithScene:[self scene] andChannel:channel];
//		[[self stack] pushController:m_channelSwitchController];
//		
//		return;
//	}


	
	if(cacheEntry != nil){
		urlString = cacheEntry;
	}else{
		//clip is not in cache, ask cahche to start download or to return the current downloader in case of a download in progress
		NSString* cachePath;
		CTVHTTPMediaDownload* downloader = [[CTVCache GetInstance] cacheURLString:urlString cachePathNoExt:&cachePath andClip:clip];
		
		
		//show download screen
		CGImageRef img = [[CTVCache GetInstance] CreateImageForURLString:[clip getThumbUrl]];
		if(img == nil && [clip getThumbUrl] != nil){
			img = (CGImageRef)CreateImageForURL( [clip getThumbUrl] );
		}
	
		if(m_downloadController != nil){
			[m_downloadController release];
		}
		m_downloadController = [[CTVMediaDownloadController alloc] initWithScene:[self scene] andClip:clip andImage:img andMediaDownload:downloader andTitle:[clip getTitle] forChannel:channel ];
		[[self stack] pushController:m_downloadController];

		[clip release];
		[channel release];

		return;
	}
	
	
	/*
	 * Intro: Clip is in cache, play the intro first if not already done
	 */
	if([[[NSUserDefaults standardUserDefaults] objectForKey:CTVCONF_PLAYINTRO] isEqualToString:@"Yes"] ){

		 if( ![[clip getUrl] isEqualToString:m_introID] ){
			
			if(m_introController != nil){
				[m_introController release];
			}
			m_introController = [[CTVIntroPlayerController alloc] initWithScene:[self scene] introduceClip:clip forChannel:channel];
			[[self stack] pushController:m_introController];
			[m_introController play];
					
			[m_introID release];
			m_introID = [clip getUrl];
			[m_introID retain];
			
			[clip release];
			[channel release];

			return;
		 }
	}
		
	/* 
	 * Play: Clip is in cache, play it using the m_videoPlayerController			
	 */
	 									
	if( [urlString hasPrefix:@"http"] == YES  ){
		mediaURL = [NSURL URLWithString:urlString];
	}else{
		mediaURL = [NSURL fileURLWithPath:urlString];
	}

	//Asset with URL
	BRSimpleMediaAsset *asset = [[[BRSimpleMediaAsset alloc] initWithMediaURL:mediaURL] autorelease];
	
	//Player, set media asset
	BRQTKitVideoPlayer* player = [channel playerForMediaURLString:urlString];
//	id player = [[[BRQTKitVideoPlayer alloc] init] autorelease];
//	[player resetPlayer];
	if([player media] == nil){
NSLog(@"[player media] == nil");	
		[player setMedia: asset error:&error];
	}

	//to the screen; controller, set player
	if(m_videoPlayerController != nil){
		[m_videoPlayerController release];
	}
	m_videoPlayerController = [[CTVVideoPlayerController alloc] initWithScene:[self scene] andClip:clip];
	[m_videoPlayerController setVideoPlayer:player];

	[[self stack] pushController:m_videoPlayerController];
	
	
	//Show channel info (only by channel switch)
	if(m_showInfoController	!= nil){
		[m_showInfoController release];
	}
	m_showInfoController = [[CTVChannelInfoOverlayController alloc] initWithScene:[self scene] andChannel:channel andTimeOut:6.0];
	[[self stack] pushController:m_showInfoController];


	
	
	//Position at the last stop
	if([[[NSUserDefaults standardUserDefaults] objectForKey:CTVCONF_CHANNELVIEW] isEqualToString:@"Yes"] ){
		[[m_videoPlayerController videoPlayer] setElapsedPlaybackTime:[[channel watchPoint] offset]];
		NSLog(@"SET; setElapsedPlaybackTime; [[tmpChannel watchPoint] offset] = %f; \n channel=%@", [[channel watchPoint] offset], [channel name] );
	}

	/*
	 * start downloading the next 1 clip
	 */
	if([[[NSUserDefaults standardUserDefaults] objectForKey:CTVCONF_CHANNELVIEW] isEqualToString:@"Yes"] ){
 
		CTVClip* nextClip = [self getNearClip:1];
		if(nextClip == nil){
			NSLog(@"nextClip = nil");
		}else{
			NSLog(@"nextClip = %@", [nextClip getTitle] );
			[[CTVCache GetInstance] cacheMedia:[nextClip getUrl] andClip:nextClip];
		}
	}
	
	[clip release];
	[channel release];

}



//+n = n-newer clip
//-n = n-older clip
-(CTVClip*)getNearClip:(int)distance{
	CTVClip* clip = [[CTVNavigationManager GetInstance] currentClip]; 
	CTVClip* tmpClip;
	CTVChannel* channel = [clip pChannel];
	int tel;
	int tmpIndex;
	//First search the current clip position in the channel based on the clipID
	int count = [channel count];
	tmpIndex = -1;
	for(tel=0;tel<count;tel++){
		tmpClip = [channel GetProgramAtIndex:tel];
		if( [[tmpClip clipID] isEqualToString:[clip clipID]] == TRUE ){
			tmpIndex = tel;
			break;
		}
	}
	
	if(tmpIndex != -1){
		tmpIndex = tmpIndex - distance; 
	}
	
	if(tmpIndex < 0 || tmpIndex > count){
		return nil;
	}

	
	return [channel GetProgramAtIndex:tmpIndex];
}



-(void)wasBuriedByPushingController:(id)controller{
	[super wasBuriedByPushingController:controller];	
}



- (void)wasExhumedByPoppingController:(id)controller{
	
	[super wasExhumedByPoppingController:controller];	

	
	/*
	 * Channel Mode
	 */
	if([[[NSUserDefaults standardUserDefaults] objectForKey:CTVCONF_CHANNELVIEW] isEqualToString:@"Yes"] ){

		if(controller == m_videoPlayerController){
//			//Keep the position
//			CTVClip* clip = [[CTVNavigationManager GetInstance] currentClip]; 
//			CTVChannel* channel = [clip pChannel];
//			[[channel watchPoint] setOffset:[[m_videoPlayerController videoPlayer] elapsedPlaybackTime]];
//NSLog(@"GET; elapsedPlaybackTime; [[m_videoPlayerController videoPlayer] elapsedPlaybackTime] = %f \n channel=%@", [[m_videoPlayerController videoPlayer] elapsedPlaybackTime], [channel name] );

			//Check if the user wants a channel switch
			if( [(CTVVideoPlayerController*)controller playOtherChannel] == YES ){
				m_channelSwtichInvoked = TRUE;

				//Keep the position
//				if(m_oldChannel){
//					[[m_oldChannel watchPoint] setOffset:[[m_videoPlayerController videoPlayer] elapsedPlaybackTime]];
//					NSLog(@"GET; elapsedPlaybackTime; [[m_videoPlayerController videoPlayer] elapsedPlaybackTime] = %f \n channel=%@", [[m_videoPlayerController videoPlayer] elapsedPlaybackTime], [channel name] );
//				}
				CTVChannel* nextChannel = [[CTVNavigationManager GetInstance] currentChannel];
				if(nextChannel == nil){
					//Remove ourselves from screen
					[[self stack] removeController:self];					
				}else{
				
					[self playClipTimed];
				}
			}else{
				//Not a channel switch
				if( [(CTVVideoPlayerController*)controller playClipNext] == YES ){
					//play next clip, if any, if not, stop
					CTVClip* nextClip = [[CTVNavigationManager GetInstance] nextClip]; 
					if(nextClip == nil){
						[[self stack] removeController:self];
					}
					[self playClipTimed];						
				}else{
					//Stop
					[[self stack] removeController:self];						
				}	
			}
		}else if(controller == m_channelSwitchController){
			//Play the next selected channel
			[self playClipTimed];
		}else if(controller == m_downloadController){
			if( [(CTVMediaDownloadController*)controller playChannelPrev] == YES){
				m_channelSwtichInvoked = TRUE;
				CTVChannel* prevChannel = [[CTVNavigationManager GetInstance] prevChannel];
				if(prevChannel == nil){
					//Remove ourselves from screen
					[[self stack] removeController:self];					
				}else{
					[self channelSwitchTimed];
				}				
			}else if([(CTVMediaDownloadController*)controller playChannelNext] == YES){
				m_channelSwtichInvoked = TRUE;
				CTVChannel* nextChannel = [[CTVNavigationManager GetInstance] nextChannel];
				if(nextChannel == nil){
					//Remove ourselves from screen
					[[self stack] removeController:self];					
				}else{
					[self channelSwitchTimed];
				}
			}else{
			 
				//Download finished, play clip now (only if controller say's it)
				if( [(CTVMediaDownloadController*)controller skipClip] == YES){
					[[CTVNavigationManager GetInstance] nextClip];
					[self playClipTimed];
				}else if( [(CTVMediaDownloadController*)controller playClipNow] == NO){
					//interrupted by user, remove ourselves from screen to go back to channel menu
					[[self stack] removeController:self];
				}else{
					[self playClipTimed];
				}
			}
		}else if(controller == m_introController){
			//Intro finished, play clip now
			if( [(CTVIntroPlayerController*)controller playClipNow] == NO){
				//interrupted by user, remove ourselves from screen to go back to channel menu
				[[self stack] removeController:self];
			}else{
				[self playClipTimed];			
			}
		}
	}else{
	/*
	 * Clip Mode
	 */
		if(controller == m_videoPlayerController){
			//Video playback ended, show rating
			[[self stack] pushController:m_rateController];
		}else if(controller == m_rateController){
			//Remove ourselves from screen
			[[self stack] removeController:self];	
		}else if(controller == m_downloadController){
			if([m_downloadController playClipNow] == TRUE){
				[self playClip];
			}else{
				//Remove ouselves from screen
				[[self stack] removeController:self];	
			}
		}
	}
}


- (BOOL)brEventAction:(BREvent*)event{
	BOOL ret;

	//We are only interested in the key-down events.
	if([event value] == 0){
		return [super brEventAction:event];
	}


//CTVClip* c;	
	switch([event remoteAction]){
		case kBRRemoteActionMenu:
			m_stopPlaying = YES;
			//Pause playback
NSLog(@"Channel Next, pause playback....");
			
			break;
		case kBRRemoteActionUp:
		
NSLog(@"Channel Next....");
//			ret = TRUE;
			break;
		case kBRRemoteActionDown:
		
NSLog(@"Channel Back...");
//			ret = TRUE;			
			break;
	}

//if([event remoteAction] != kBRRemoteActionDown && [event remoteAction] != kBRRemoteActionUp){
	ret = [super brEventAction:event];
//}
	
	return ret;
}


- (id)popAnimation{
	id animation = [super popAnimation];
	return animation;
}


- (id)pushAnimation{
	id animation = [super pushAnimation];
	return animation;
}

- (BOOL)firstResponder{
//	NSLog(@"firstResponder");
	return [super firstResponder];
}


- (void)activate{
	
}

- (void)willLoseFocus{
	NSLog(@"willLoseFocus");

}

- (id)exhumeAnimationWithPoppingController:(id)fp8{
	NSLog(@"exhumeAnimationWithPoppingController");
	id animation = [super exhumeAnimationWithPoppingController:fp8];
		
	return animation;
}


- (void)willRegainFocus{
	NSLog(@"willRegainFocus");
	
}

- (void)willDeactivate{
	NSLog(@"willDeactivate");

}

- (void)deactivate{
	NSLog(@"deactivate");

}

- (BOOL)fadeLayerIn{
	return TRUE;
}

- (void)setDeletterboxAssetArtwork:(BOOL)fp8{
	NSLog(@"setDeletterboxAssetArtwork");

}

- (id)layer{
	return _master;
}


-(void)channelSwitchTimed{
[self _channelSwitchTimed:nil];
//
//	if(m_channelSwitchTimer)[m_channelSwitchTimer invalidate];
//	m_channelSwitchTimer = [NSTimer scheduledTimerWithTimeInterval:0.25f target:self selector:@selector(_channelSwitchTimed:) userInfo:nil repeats:NO];
//	[m_channelSwitchTimer retain];

}



-(void)playClipTimed{
	if(m_playClipTimer)[m_playClipTimer invalidate];
	m_playClipTimer = [NSTimer scheduledTimerWithTimeInterval:0.30f target:self selector:@selector(_playClipTimed:) userInfo:nil repeats:NO];
	[m_playClipTimer retain];
}

-(void)_playClipTimed:(NSTimer*)timer{
	[self playClip];
}

-(void)_channelSwitchTimed:(NSTimer*)timer{
		if(m_channelSwitchController != nil){
			[m_channelSwitchController release];
		}
		CTVChannel* channel = [[CTVNavigationManager GetInstance] currentChannel] ;
		m_channelSwitchController = [[CTVChannelSwitchInfoController alloc] initWithScene:[self scene] andChannel:channel];
		[[self stack] pushController:m_channelSwitchController];
}


-(void)_layout{
	CTVClip* clip = [[CTVNavigationManager GetInstance] currentClip]; 
	//Lay-Out	
	if([clip thumbTexture] == nil){
		[clip loadBitmapTextureForScene:[self scene]];
	}
	
	NSRect masterFrame = [[self masterLayer] frame];
	[m_bgimage setTexture:[clip thumbTexture]];
	[m_bgimage setFrame:masterFrame];
}

@end


